#ifndef jolfs_inode_h_
#define jolfs_inode_h_

#include "jolfs/types.h"

#include <string>
#include <ctime>
#include <map>

namespace jolfs
{

  //
  // Inode class
  //
  // An inode must be unique on a filesystem even if
  // if it is a distributed filesystem.
  // However, when there is some replication of a same
  // file on several server, we have to keep a list of
  // which server has this inode.
  //
  // An inode contains these information:
  // - name
  // - access right (ugo+rwx)
  // - status of the file:
  //   open, lock, write, read, delete.
  // - type {LINK, DIRECTORY, FILE, ETC.}
  // 
  // 
  class INode
  {
  public:
    // TYPEDEFS
    typedef unsigned char                 status_t;
    typedef boost::uint8_t                type_t;
    typedef std::map<std::string, INode*> Map;

  public:
    


    // CONSTRUCTORS
    INode(const std::string& name);
    INode(const std::string& name, mode_t mode, type_t type, filesize_t size);
    
    
    // GETTERS/SETTERS
    void        setParent(INode* p);
    INode*      getParent() const;

    void        setSize(const filesize_t s);
    filesize_t  getSize() const;
    
    void        setMode(const mode_t m);
    mode_t      getMode() const;
    
    void        setType(const type_t t);
    type_t      getType();

    void        setStatus(const status_t s);
    status_t    getStatus();

    void        setName(const std::string& name);
    std::string getName() const;

    void        setLastAccess(const timestamp_t y);
    timestamp_t getLastAccess() const;
    
    //
    // METHODS
    //

    // Create a child and append it to this INode. If the child
    // already exists return Null
    // @param name: the name of the INode to create.
    // @param mode: the access right
    // @param size: the size of the created node.
    INode* createChild(const std::string& name,
		       mode_t mode, type_t type, filesize_t size);

    

  private:
    
    // ATTRIBUTES
    INode*       parent_;
    
    filesize_t   size_;
    mode_t       mode_;
    status_t     status_;
    type_t       type_;
    
    std::string  name_;  

    Map*         child_;

    timestamp_t  lastAccess_;
  };


  // ---------------------------------------------
  // I N L I N E S
  // ---------------------------------------------

  inline INode::INode(const std::string& name) : 
    parent_(NULL), size_(0), mode_(0), status_(0), 
    name_(name), child_(NULL), lastAccess_(time(NULL))
  {
  }
    
  inline INode::INode(const std::string& name, mode_t mode, INode::type_t type, filesize_t size) :
    parent_(NULL), size_(size), mode_(mode), status_(0), type_(type), 
    name_(name), child_(NULL), lastAccess_(time(NULL))
  {
    
  }
  

  inline void INode::setParent(INode* p)
  {
    parent_ = p;
  }

  // ---------------------------------------------

  inline INode* INode::getParent() const
  {
    return parent_;
  }

  // ---------------------------------------------

  inline void  INode::setSize(const filesize_t s)
  {
    size_ = s;
  }

  // ---------------------------------------------

  inline filesize_t INode::getSize() const
  {
    return size_;
  }
  
  // ---------------------------------------------

  inline void INode::setMode(const mode_t m)
  {
    mode_ = m;
  }

  // ---------------------------------------------

  inline mode_t INode::getMode() const
  {
    return mode_;
  }

  // ---------------------------------------------
  
  inline void INode::setType(const INode::type_t t)
  {
    type_ = t;
  }

  // ---------------------------------------------

  inline INode::type_t INode::getType()
  {
    return type_;
  }

  // ---------------------------------------------
  
  inline void INode::setStatus(const INode::status_t s)
  {
    status_ = s;
  }

  // ---------------------------------------------

  inline INode::status_t INode::getStatus()
  {
    return status_;
  }

  // ---------------------------------------------

  inline void INode::setName(const std::string& name)
  {
    name_ = name;
  }
  
  // ---------------------------------------------

  inline std::string INode::getName() const
  {
    return name_;
  }

  // ---------------------------------------------

  inline void INode::setLastAccess(const timestamp_t t)
  {
    lastAccess_ = t;
  }
  
  // ---------------------------------------------

  inline timestamp_t  INode::getLastAccess() const
  {
    return lastAccess_;
  }

} // jolfs


#endif
